package test.myorm.core;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;

public class MapperProxy implements InvocationHandler {
	
	private Configuration configuration;
	private Class clazz;
	private SqlSession sqlSession;
	
	public MapperProxy(Configuration configuration, Class clazz, SqlSession sqlSession) {
		this.configuration = configuration;
		this.clazz = clazz;
		this.sqlSession = sqlSession;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		String key = clazz.getName() + "." + method.getName();
		Sql sql = configuration.getSqlMap().get(key);
		
		int sqlType = sql.getType();
		boolean multiResult = false;
		if(sqlType==Sql.SQL_SELECT) {
			ResultMap resultMap = sql.getResultMap();
			Class resultClass = resultMap.getClazz();
			Class returnType = method.getReturnType();
			if((resultClass==null && returnType!=null) || (resultClass!=null && returnType==null)) {
				throw new RuntimeException("方法的返回值类型[" + returnType + "]与mapper配置[" + resultClass + "]不符!!!");
			}
			multiResult = returnType.equals(List.class);
			if(returnType!=null && resultClass!=returnType && !multiResult && resultClass.equals(HashMap.class)) {
				resultClass = returnType;
				resultMap.setClazz(resultClass);
			}
			if(resultClass!=null && returnType!=null&& !multiResult && !resultClass.equals(returnType)) {
				throw new RuntimeException("方法的返回值类型[" + returnType + "]与mapper配置[" + resultClass + "]不符!!!");
			}
		}
		
		if(sqlType==Sql.SQL_SELECT) {
			if(multiResult) {
				return sqlSession.selectList(key, args);
			} else {
				return sqlSession.selectOne(key, args);
			}
		} else if(sqlType==Sql.SQL_INSERT) {
			return sqlSession.update(key, args);
		} else if(sqlType==Sql.SQL_UPDATE) {
			return sqlSession.update(key, args);
		} else if(sqlType==Sql.SQL_DELETE) {
			return sqlSession.update(key, args);
		} else {
			throw new RuntimeException("wrong sqlType(" + sqlType + ")");
		}
	}

}
